#include <iostream>
#include <cmath>

#include <osmscout/util/String.h>

#include <catch2/catch_test_macros.hpp>

TEST_CASE("Split empty string")
{
  auto elements = osmscout::SplitString("", ";");
  REQUIRE(elements.empty());
}

TEST_CASE("Split string by simple separator")
{
  auto elements=osmscout::SplitString("asphalt;ground;gravel", ";");
  REQUIRE(elements.size() == 3);
  auto it=elements.begin();
  REQUIRE(*(it++) == "asphalt");
  REQUIRE(*(it++) == "ground");
  REQUIRE(*(it++) == "gravel");
}

TEST_CASE("Separator on the end dont produce empty element")
{
  auto elements=osmscout::SplitString(";asphalt;ground;gravel;", ";");
  REQUIRE(elements.size() == 4);
  auto it=elements.begin();
  REQUIRE(*(it++) == "");
  REQUIRE(*(it++) == "asphalt");
  REQUIRE(*(it++) == "ground");
  REQUIRE(*(it++) == "gravel");
}

TEST_CASE("Split string by multi-character separator")
{
  auto elements=osmscout::SplitString("asphalt <> ground <> gravel", " <> ");
  REQUIRE(elements.size() == 3);
  auto it=elements.begin();
  REQUIRE(*(it++) == "asphalt");
  REQUIRE(*(it++) == "ground");
  REQUIRE(*(it++) == "gravel");
}

TEST_CASE("Split empty string to pair")
{
  auto elements = osmscout::SplitStringToPair("", ";");
  REQUIRE_FALSE(elements.has_value());
}

TEST_CASE("Split string with multiple separators to pair")
{
  auto elements = osmscout::SplitStringToPair("a;b;c;", ";");
  REQUIRE(elements.has_value());
  REQUIRE(std::get<0>(elements.value())=="a");
  REQUIRE(std::get<1>(elements.value())=="b;c;");
}

TEST_CASE("Split string with separator on the end")
{
  auto elements = osmscout::SplitStringToPair("a;", ";");
  REQUIRE(elements.has_value());
  REQUIRE(std::get<0>(elements.value())=="a");
  REQUIRE(std::get<1>(elements.value()).empty());
}

TEST_CASE("Split string just with separator")
{
  auto elements = osmscout::SplitStringToPair(";", ";");
  REQUIRE(elements.has_value());
  REQUIRE(std::get<0>(elements.value()).empty());
  REQUIRE(std::get<1>(elements.value()).empty());
}

TEST_CASE("Transliterate diacritics")
{
  try {
    std::locale::global(std::locale("C"));
    std::cout << "C locale activated" << std::endl;
  } catch (const std::exception& e) {
    std::cerr << "ERROR: Cannot set locale: " << e.what() << std::endl;
  }

  auto transformed=osmscout::UTF8Transliterate(
    "\xc3\xa1\xc3\xa9\xc3\xad\xc3\xbd\xc3\xb3\xc3\xba\xc5\xaf\xc4\x8f\xc5\xa5\xc5\x88\xc4\x9b"
    "\xc5\xa1\xc4\x8d\xc5\x99\xc5\xbe\xc3\xbc\xc3\xb6\xc3\x81\xc3\x89\xc3\x8d\xc3\x9d\xc3\x93"
    "\xc3\x9a\xc5\xae\xc4\x8e\xc5\xa4\xc5\x87\xc4\x9a\xc5\xa0\xc4\x8c\xc5\x98\xc5\xbd\xc3\x9c"
    "\xc3\x96\xc3\x9f\xc3\xa6\xc3\x86"
  );

  REQUIRE(transformed ==
    "aeiyouudtnescrzuoAEIYOUUDTNESCRZUOssaeAE");
}

TEST_CASE("Transliterate untranslated")
{
  auto transformed=osmscout::UTF8Transliterate(
    "\xc3\xa1\xc3\xa9\xc3\xad\xc3\xbd\xc3\xb3\xc3\xba\xc5\xaf\xc4\x8f\xc5\xa5\xc5\x88\xc4\x9b"
    "\xc5\xa1\xc4\x8d\xc5\x99\xc5\xbe\xc3\xbc\xc3\xb6\x20\xd4\xb4\xd5\xb8\xd6\x82\xd6\x84\x20"
    "\xd5\xb9\xd5\xb0\xd5\xa1\xd5\xbd\xd5\xaf\xd5\xa1\xd6\x81\xd5\xa1\xd6\x84\x20\xd5\xab\xd5\xb4"
    "\x20\xd5\xba\xd5\xa1\xd6\x80\xd5\xa6\xd5\xb8\xd6\x82\xd5\xa9\xd5\xb5\xd5\xb8\xd6\x82\xd5\xb6"
    "\xd5\xa8\x20\xc3\x81\xc3\x89\xc3\x8d\xc3\x9d\xc3\x93\xc3\x9a\xc5\xae\xc4\x8e\xc5\xa4\xc5\x87"
    "\xc4\x9a\xc5\xa0\xc4\x8c\xc5\x98\xc5\xbd\xc3\x9c\xc3\x96\xc3\x9f\xc3\xa6\xc3\x86"
  );

  REQUIRE(transformed ==
    "\x61\x65\x69\x79\x6f\x75\x75\x64\x74\x6e\x65\x73\x63\x72\x7a\x75\x6f\x20\xd4\xb4\xd5\xb8"
    "\xd6\x82\xd6\x84\x20\xd5\xb9\xd5\xb0\xd5\xa1\xd5\xbd\xd5\xaf\xd5\xa1\xd6\x81\xd5\xa1\xd6\x84"
    "\x20\xd5\xab\xd5\xb4\x20\xd5\xba\xd5\xa1\xd6\x80\xd5\xa6\xd5\xb8\xd6\x82\xd5\xa9\xd5\xb5"
    "\xd5\xb8\xd6\x82\xd5\xb6\xd5\xa8\x20\x41\x45\x49\x59\x4f\x55\x55\x44\x54\x4e\x45\x53\x43\x52"
    "\x5a\x55\x4f\x73\x73\x61\x65\x41\x45"
  );
}

TEST_CASE("Uppercase 1")
{
  auto transformed=osmscout::UTF8StringToUpper(
    "\xc3\xa1\xc3\xa9\xc3\xad\xc3\xbd\xc3\xb3\xc3\xba\xc5\xaf\xc4\x8f\xc5\xa5\xc5\x88\xc4\x9b"
    "\xc5\xa1\xc4\x8d\xc5\x99\xc5\xbe\xc3\xbc\xc3\xb6\xc3\xbf\xc3\x81\xc3\x89\xc3\x8d\xc3\x9d"
    "\xc3\x93\xc3\x9a\xc5\xae\xc4\x8e\xc5\xa4\xc5\x87\xc4\x9a\xc5\xa0\xc4\x8c\xc5\x98\xc5\xbd"
    "\xc3\x9c\xc3\x96\xc5\xb8\xc3\x9f"
  );

  REQUIRE(transformed ==
    "\xc3\x81\xc3\x89\xc3\x8d\xc3\x9d\xc3\x93\xc3\x9a\xc5\xae\xc4\x8e\xc5\xa4\xc5\x87\xc4\x9a"
    "\xc5\xa0\xc4\x8c\xc5\x98\xc5\xbd\xc3\x9c\xc3\x96\xc5\xb8\xc3\x81\xc3\x89\xc3\x8d\xc3\x9d"
    "\xc3\x93\xc3\x9a\xc5\xae\xc4\x8e\xc5\xa4\xc5\x87\xc4\x9a\xc5\xa0\xc4\x8c\xc5\x98\xc5\xbd"
    "\xc3\x9c\xc3\x96\xc5\xb8\xc3\x9f"
  );
}

TEST_CASE("Lowercase 1")
{
  auto transformed=osmscout::UTF8StringToLower(
    "\xc3\xa1\xc3\xa9\xc3\xad\xc3\xbd\xc3\xb3\xc3\xba\xc5\xaf\xc4\x8f\xc5\xa5\xc5\x88\xc4\x9b"
    "\xc5\xa1\xc4\x8d\xc5\x99\xc5\xbe\xc3\xbc\xc3\xb6\xc3\xbf\xc3\x81\xc3\x89\xc3\x8d\xc3\x9d"
    "\xc3\x93\xc3\x9a\xc5\xae\xc4\x8e\xc5\xa4\xc5\x87\xc4\x9a\xc5\xa0\xc4\x8c\xc5\x98\xc5\xbd"
    "\xc3\x9c\xc3\x96\xc5\xb8\xc3\x9f"
  );

  REQUIRE(transformed ==
    "\xc3\xa1\xc3\xa9\xc3\xad\xc3\xbd\xc3\xb3\xc3\xba\xc5\xaf\xc4\x8f\xc5\xa5\xc5\x88\xc4\x9b"
    "\xc5\xa1\xc4\x8d\xc5\x99\xc5\xbe\xc3\xbc\xc3\xb6\xc3\xbf\xc3\xa1\xc3\xa9\xc3\xad\xc3\xbd"
    "\xc3\xb3\xc3\xba\xc5\xaf\xc4\x8f\xc5\xa5\xc5\x88\xc4\x9b\xc5\xa1\xc4\x8d\xc5\x99\xc5\xbe"
    "\xc3\xbc\xc3\xb6\xc3\xbf\xc3\x9f"
  );
}

TEST_CASE("Uppercase 2")
{
  auto transformed=osmscout::UTF8StringToUpper(
    "\xce\x94\xce\xb5\xce\xbd\x20\xce\xba\xce\xb1\xcf\x84\xce\xb1\xce\xbb\xce\xac\xce\xb2\xce\xb1"
    "\xcf\x84\xce\xb5\x20\xcf\x84\xce\xaf\xcf\x80\xce\xbf\xcf\x84\xce\xb1\x20\xce\xb1\xcf\x80"
    "\xcf\x8c\x20\xcf\x84\xce\xb7\xce\xbd\x20\xce\xb1\xcf\x80\xce\xbb\xcf\x8c\xcf\x84\xce\xb7"
    "\xcf\x84\xce\xac\x20\xce\xbc\xce\xbf\xcf\x85\x2c\x20\xcf\x84\xce\xaf\xcf\x80\xce\xbf\xcf\x84"
    "\xce\xb1\x2c\x20\xcf\x89\x20\xcf\x86\xcf\x84\xcf\x89\xcf\x87\xcf\x8c\x20\xcf\x80\xce\xb1"
    "\xce\xb9\xce\xb4\xce\xaf\x20\xce\xbc\xce\xbf\xcf\x85\x21\x20\xce\x9a\xce\xb1\xce\xb9\x20"
    "\xce\xb5\xce\xaf\xce\xbd\xce\xb1\xce\xb9\x20\xce\xbc\xce\xb5\x20\xce\xad\xce\xbd\xce\xb1\x20"
    "\xcf\x80\xce\xb1\xce\xbb\xce\xb9\xcf\x8c\x20\xcf\x86\xcf\x81\xcf\x8d\xce\xb4\xce\xb9\x2c\x20"
    "\xce\xb5\xce\xbd\xce\xbf\xcf\x87\xce\xbb\xce\xb7\xce\xbc\xce\xad\xce\xbd\xce\xbf\x20\xcf\x80"
    "\xce\xbf\xcf\x85\x20\xcf\x86\xce\xb5\xcf\x8d\xce\xb3\xce\xb5\xce\xb9\xcf\x82\x20\xcf\x80"
    "\xcf\x81\xce\xb9\xce\xbd\x2e"
  );

  REQUIRE(transformed ==
    "\xce\x94\xce\x95\xce\x9d\x20\xce\x9a\xce\x91\xce\xa4\xce\x91\xce\x9b\xce\x86\xce\x92\xce\x91"
    "\xce\xa4\xce\x95\x20\xce\xa4\xce\x8a\xce\xa0\xce\x9f\xce\xa4\xce\x91\x20\xce\x91\xce\xa0"
    "\xce\x8c\x20\xce\xa4\xce\x97\xce\x9d\x20\xce\x91\xce\xa0\xce\x9b\xce\x8c\xce\xa4\xce\x97"
    "\xce\xa4\xce\x86\x20\xce\x9c\xce\x9f\xce\xa5\x2c\x20\xce\xa4\xce\x8a\xce\xa0\xce\x9f\xce\xa4"
    "\xce\x91\x2c\x20\xce\xa9\x20\xce\xa6\xce\xa4\xce\xa9\xce\xa7\xce\x8c\x20\xce\xa0\xce\x91"
    "\xce\x99\xce\x94\xce\x8a\x20\xce\x9c\xce\x9f\xce\xa5\x21\x20\xce\x9a\xce\x91\xce\x99\x20"
    "\xce\x95\xce\x8a\xce\x9d\xce\x91\xce\x99\x20\xce\x9c\xce\x95\x20\xce\x88\xce\x9d\xce\x91\x20"
    "\xce\xa0\xce\x91\xce\x9b\xce\x99\xce\x8c\x20\xce\xa6\xce\xa1\xce\x8e\xce\x94\xce\x99\x2c\x20"
    "\xce\x95\xce\x9d\xce\x9f\xce\xa7\xce\x9b\xce\x97\xce\x9c\xce\x88\xce\x9d\xce\x9f\x20\xce\xa0"
    "\xce\x9f\xce\xa5\x20\xce\xa6\xce\x95\xce\x8e\xce\x93\xce\x95\xce\x99\xce\xa3\x20\xce\xa0"
    "\xce\xa1\xce\x99\xce\x9d\x2e"
  );
}

TEST_CASE("Lowercase 2")
{
  auto transformed=osmscout::UTF8StringToLower(
    "\xce\x94\xce\x95\xce\x9d\x20\xce\x9a\xce\x91\xce\xa4\xce\x91\xce\x9b\xce\x86\xce\x92\xce\x91"
    "\xce\xa4\xce\x95\x20\xce\xa4\xce\x8a\xce\xa0\xce\x9f\xce\xa4\xce\x91\x20\xce\x91\xce\xa0"
    "\xce\x8c\x20\xce\xa4\xce\x97\xce\x9d\x20\xce\x91\xce\xa0\xce\x9b\xce\x8c\xce\xa4\xce\x97"
    "\xce\xa4\xce\x86\x20\xce\x9c\xce\x9f\xce\xa5\x2c\x20\xce\xa4\xce\x8a\xce\xa0\xce\x9f\xce\xa4"
    "\xce\x91\x2c\x20\xce\xa9\x20\xce\xa6\xce\xa4\xce\xa9\xce\xa7\xce\x8c\x20\xce\xa0\xce\x91"
    "\xce\x99\xce\x94\xce\x8a\x20\xce\x9c\xce\x9f\xce\xa5\x21\x20\xce\x9a\xce\x91\xce\x99\x20"
    "\xce\x95\xce\x8a\xce\x9d\xce\x91\xce\x99\x20\xce\x9c\xce\x95\x20\xce\x88\xce\x9d\xce\x91\x20"
    "\xce\xa0\xce\x91\xce\x9b\xce\x99\xce\x8c\x20\xce\xa6\xce\xa1\xce\x8e\xce\x94\xce\x99\x2c\x20"
    "\xce\x95\xce\x9d\xce\x9f\xce\xa7\xce\x9b\xce\x97\xce\x9c\xce\x88\xce\x9d\xce\x9f\x20\xce\xa0"
    "\xce\x9f\xce\xa5\x20\xce\xa6\xce\x95\xce\x8e\xce\x93\xce\x95\xce\x99\xce\xa3\x20\xce\xa0"
    "\xce\xa1\xce\x99\xce\x9d\x2e"
  );

  REQUIRE(transformed ==
    "\xce\xb4\xce\xb5\xce\xbd\x20\xce\xba\xce\xb1\xcf\x84\xce\xb1\xce\xbb\xce\xac\xce\xb2\xce\xb1"
    "\xcf\x84\xce\xb5\x20\xcf\x84\xce\xaf\xcf\x80\xce\xbf\xcf\x84\xce\xb1\x20\xce\xb1\xcf\x80"
    "\xcf\x8c\x20\xcf\x84\xce\xb7\xce\xbd\x20\xce\xb1\xcf\x80\xce\xbb\xcf\x8c\xcf\x84\xce\xb7"
    "\xcf\x84\xce\xac\x20\xce\xbc\xce\xbf\xcf\x85\x2c\x20\xcf\x84\xce\xaf\xcf\x80\xce\xbf\xcf\x84"
    "\xce\xb1\x2c\x20\xcf\x89\x20\xcf\x86\xcf\x84\xcf\x89\xcf\x87\xcf\x8c\x20\xcf\x80\xce\xb1"
    "\xce\xb9\xce\xb4\xce\xaf\x20\xce\xbc\xce\xbf\xcf\x85\x21\x20\xce\xba\xce\xb1\xce\xb9\x20"
    "\xce\xb5\xce\xaf\xce\xbd\xce\xb1\xce\xb9\x20\xce\xbc\xce\xb5\x20\xce\xad\xce\xbd\xce\xb1\x20"
    "\xcf\x80\xce\xb1\xce\xbb\xce\xb9\xcf\x8c\x20\xcf\x86\xcf\x81\xcf\x8d\xce\xb4\xce\xb9\x2c\x20"
    "\xce\xb5\xce\xbd\xce\xbf\xcf\x87\xce\xbb\xce\xb7\xce\xbc\xce\xad\xce\xbd\xce\xbf\x20\xcf\x80"
    "\xce\xbf\xcf\x85\x20\xcf\x86\xce\xb5\xcf\x8d\xce\xb3\xce\xb5\xce\xb9\xcf\x83\x20\xcf\x80"
    "\xcf\x81\xce\xb9\xce\xbd\x2e"
  );
}

TEST_CASE("Uppercase 3")
{
  auto transformed=osmscout::UTF8StringToUpper(
    "\xd9\x84\xd9\x85\x20\xd8\xaa\xd9\x81\xd9\x87\xd9\x85\x20\xd8\xb4\xd9\x8a\xd8\xa6\xd9\x8b"
    "\xd8\xa7\x20\xd9\x85\xd9\x86\x20\xd8\xa8\xd8\xb3\xd8\xa7\xd8\xb7\xd8\xaa\xd9\x8a\x20\xd8\x8c"
    "\x20\xd9\x84\xd8\xa7\x20\xd8\xb4\xd9\x8a\xd8\xa1\x20\xd8\x8c\x20\xd9\x8a\xd8\xa7\x20\xd9\x88"
    "\xd9\x84\xd8\xaf\xd9\x8a\x20\xd8\xa7\xd9\x84\xd9\x85\xd8\xb3\xd9\x83\xd9\x8a\xd9\x86\x21\x20"
    "\xd9\x88\xd9\x85\xd8\xb9\x20\xd8\xac\xd8\xa8\xd9\x8a\xd9\x86\x20\xd9\x84\xd8\xa7\x20\xd9\x85"
    "\xd8\xb9\xd9\x86\xd9\x89\x20\xd9\x84\xd9\x87\x20\xd8\x8c\x20\xd9\x85\xd9\x86\xd8\xb2\xd8\xb9"
    "\xd8\xac\x20\xd8\xa3\xd9\x86\x20\xd8\xaa\xd9\x87\xd8\xb1\xd8\xa8\x20\xd9\x85\xd9\x86\x20"
    "\xd9\x82\xd8\xa8\xd9\x84\x2e"
  );

  REQUIRE(transformed ==
    "\xd9\x84\xd9\x85\x20\xd8\xaa\xd9\x81\xd9\x87\xd9\x85\x20\xd8\xb4\xd9\x8a\xd8\xa6\xd9\x8b"
    "\xd8\xa7\x20\xd9\x85\xd9\x86\x20\xd8\xa8\xd8\xb3\xd8\xa7\xd8\xb7\xd8\xaa\xd9\x8a\x20\xd8\x8c"
    "\x20\xd9\x84\xd8\xa7\x20\xd8\xb4\xd9\x8a\xd8\xa1\x20\xd8\x8c\x20\xd9\x8a\xd8\xa7\x20\xd9\x88"
    "\xd9\x84\xd8\xaf\xd9\x8a\x20\xd8\xa7\xd9\x84\xd9\x85\xd8\xb3\xd9\x83\xd9\x8a\xd9\x86\x21\x20"
    "\xd9\x88\xd9\x85\xd8\xb9\x20\xd8\xac\xd8\xa8\xd9\x8a\xd9\x86\x20\xd9\x84\xd8\xa7\x20\xd9\x85"
    "\xd8\xb9\xd9\x86\xd9\x89\x20\xd9\x84\xd9\x87\x20\xd8\x8c\x20\xd9\x85\xd9\x86\xd8\xb2\xd8\xb9"
    "\xd8\xac\x20\xd8\xa3\xd9\x86\x20\xd8\xaa\xd9\x87\xd8\xb1\xd8\xa8\x20\xd9\x85\xd9\x86\x20"
    "\xd9\x82\xd8\xa8\xd9\x84\x2e"
  );
}

TEST_CASE("Lowercase 3")
{
  auto transformed=osmscout::UTF8StringToLower(
    "\xd9\x84\xd9\x85\x20\xd8\xaa\xd9\x81\xd9\x87\xd9\x85\x20\xd8\xb4\xd9\x8a\xd8\xa6\xd9\x8b"
    "\xd8\xa7\x20\xd9\x85\xd9\x86\x20\xd8\xa8\xd8\xb3\xd8\xa7\xd8\xb7\xd8\xaa\xd9\x8a\x20\xd8\x8c"
    "\x20\xd9\x84\xd8\xa7\x20\xd8\xb4\xd9\x8a\xd8\xa1\x20\xd8\x8c\x20\xd9\x8a\xd8\xa7\x20\xd9\x88"
    "\xd9\x84\xd8\xaf\xd9\x8a\x20\xd8\xa7\xd9\x84\xd9\x85\xd8\xb3\xd9\x83\xd9\x8a\xd9\x86\x21\x20"
    "\xd9\x88\xd9\x85\xd8\xb9\x20\xd8\xac\xd8\xa8\xd9\x8a\xd9\x86\x20\xd9\x84\xd8\xa7\x20\xd9\x85"
    "\xd8\xb9\xd9\x86\xd9\x89\x20\xd9\x84\xd9\x87\x20\xd8\x8c\x20\xd9\x85\xd9\x86\xd8\xb2\xd8\xb9"
    "\xd8\xac\x20\xd8\xa3\xd9\x86\x20\xd8\xaa\xd9\x87\xd8\xb1\xd8\xa8\x20\xd9\x85\xd9\x86\x20"
    "\xd9\x82\xd8\xa8\xd9\x84\x2e"
  );

  REQUIRE(transformed ==
    "\xd9\x84\xd9\x85\x20\xd8\xaa\xd9\x81\xd9\x87\xd9\x85\x20\xd8\xb4\xd9\x8a\xd8\xa6\xd9\x8b"
    "\xd8\xa7\x20\xd9\x85\xd9\x86\x20\xd8\xa8\xd8\xb3\xd8\xa7\xd8\xb7\xd8\xaa\xd9\x8a\x20\xd8\x8c"
    "\x20\xd9\x84\xd8\xa7\x20\xd8\xb4\xd9\x8a\xd8\xa1\x20\xd8\x8c\x20\xd9\x8a\xd8\xa7\x20\xd9\x88"
    "\xd9\x84\xd8\xaf\xd9\x8a\x20\xd8\xa7\xd9\x84\xd9\x85\xd8\xb3\xd9\x83\xd9\x8a\xd9\x86\x21\x20"
    "\xd9\x88\xd9\x85\xd8\xb9\x20\xd8\xac\xd8\xa8\xd9\x8a\xd9\x86\x20\xd9\x84\xd8\xa7\x20\xd9\x85"
    "\xd8\xb9\xd9\x86\xd9\x89\x20\xd9\x84\xd9\x87\x20\xd8\x8c\x20\xd9\x85\xd9\x86\xd8\xb2\xd8\xb9"
    "\xd8\xac\x20\xd8\xa3\xd9\x86\x20\xd8\xaa\xd9\x87\xd8\xb1\xd8\xa8\x20\xd9\x85\xd9\x86\x20"
    "\xd9\x82\xd8\xa8\xd9\x84\x2e"
  );
}

TEST_CASE("Normalize for lookup")
{
  auto transformed=osmscout::UTF8NormForLookup("Baker \x09 \xc2\xa0 \xe2\x80\x87 \xe2\x80\xaf Street");

  REQUIRE(transformed == "baker street");
}

TEST_CASE("Check UTF8 string buffer integrity")
{
  /* Transliterate 24 POUND SIGN: IN = 48 bytes , OUT = 72 bytes */
  auto transformed=osmscout::UTF8Transliterate(
    "\xc2\xa3\xc2\xa3\xc2\xa3\xc2\xa3\xc2\xa3\xc2\xa3\xc2\xa3\xc2\xa3"
    "\xc2\xa3\xc2\xa3\xc2\xa3\xc2\xa3\xc2\xa3\xc2\xa3\xc2\xa3\xc2\xa3"
    "\xc2\xa3\xc2\xa3\xc2\xa3\xc2\xa3\xc2\xa3\xc2\xa3\xc2\xa3\xc2\xa3"
  );

  REQUIRE(transformed ==
    "GBPGBPGBPGBPGBPGBPGBPGBPGBPGBPGBPGBPGBPGBPGBPGBPGBPGBPGBPGBPGBPGBPGBPGBP");
}

TEST_CASE("Parse illegal UTF8 sequence")
{
  auto transformed=osmscout::UTF8Transliterate("\xef\xbb\xbf\x2f\xc0\xae\x2e\x2f");

  REQUIRE(transformed == "\xef\xbb\xbf\x2f\x2e\x2f");
}

TEST_CASE("Parse one UCS1 sequence without BOM")
{
  REQUIRE(osmscout::UTF8StringToUpper("z") == "Z");
}

TEST_CASE("Parse one UCS2 sequence without BOM")
{
  REQUIRE(osmscout::UTF8StringToUpper("\xc3\xae") == "\xc3\x8e");
}

TEST_CASE("Parse one UCS3 sequence without BOM")
{
  REQUIRE(osmscout::UTF8StringToUpper("\xe2\xb4\x80") == "\xe1\x82\xa0");
}

TEST_CASE("Parse one UCS4 sequence without BOM")
{
  REQUIRE(osmscout::UTF8StringToUpper("\xf0\x9e\xa4\xa2") == "\xf0\x9e\xa4\x80");
}

TEST_CASE("Local aware number to string")
{
  osmscout::Locale locale;
  locale.SetThousandsSeparator(" ");
  locale.SetDecimalSeparator(".");
  REQUIRE(osmscout::NumberToString(1002030, locale) == "1 002 030");
  REQUIRE(osmscout::NumberToString(-1002030, locale) == "-1 002 030");

  REQUIRE(osmscout::FloatToString(M_PI, locale, 2) == "3.14");
  REQUIRE(osmscout::FloatToString(-1002030.123456, locale, 6) == "-1 002 030.123 456");
  REQUIRE(osmscout::FloatToString(-1002030.125, locale, 2) == "-1 002 030.13");
}

TEST_CASE("Byte size to string")
{
  osmscout::Locale locale;
  locale.SetThousandsSeparator("'");
  locale.SetDecimalSeparator(",");
  locale.SetUnitsSeparator(" ");
  REQUIRE(osmscout::ByteSizeToString(1063256064.0, locale) == "1'014,0 MiB");
  REQUIRE(osmscout::ByteSizeToString(6406241158.0, locale) == "6,0 GiB");
}

TEST_CASE("Trim string")
{
  REQUIRE(osmscout::Trim("").empty());
  REQUIRE(osmscout::Trim("a b c")=="a b c");
  REQUIRE(osmscout::Trim("  abc  ")=="abc");
  REQUIRE(osmscout::Trim("--  abc  --", '-')=="  abc  ");
}

TEST_CASE("String replace")
{
  REQUIRE(osmscout::ReplaceString("", "a", "b").empty());
  REQUIRE(osmscout::ReplaceString("abc", "", "b")=="abc");
  REQUIRE(osmscout::ReplaceString("abcabc", "a", "A")=="AbcAbc");
  REQUIRE(osmscout::ReplaceString("abcdef", "ef", "X")=="abcdX");
  REQUIRE(osmscout::ReplaceString("abcdef", "ab", "X")=="Xcdef");
}
